package com.dingding.nettyserver.core.server;

import org.springframework.stereotype.Component;

import com.dingding.nettyserver.core.codec.RequestDecoder;
import com.dingding.nettyserver.core.codec.ResponseEncoder;
import com.dingding.nettyserver.core.config.ServerConfig;
import com.dingding.nettyserver.core.util.LogKit;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * @Description 叮叮netty服务器器的主类
 * @author fengshuonan
 * @date 2016年11月18日 下午8:54:38
 */
@Component
public class Server {
	
	// 服务类
	ServerBootstrap serverBootstrap = new ServerBootstrap();

	// 创建boss线程池，boss用来接入用户，接入之后boss安排给worker执行后续业务
	EventLoopGroup bossGroup = new NioEventLoopGroup();

	// 创建worker线程池，worker用来具体服务用户
	EventLoopGroup workerGroup = new NioEventLoopGroup();

	// 业务线程池
	EventLoopGroup serviceGroup = new NioEventLoopGroup();

	/**
	 * @Description 启动叮叮服务器
	 * @author fengshuonan
	 */
	public void start() {

		try {
			// 设置循环线程组事例
			serverBootstrap.group(bossGroup, workerGroup);

			// 设置channel工厂
			serverBootstrap.channel(NioServerSocketChannel.class);

			// 设置管道
			serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline()
							.addLast(new IdleStateHandler(ServerConfig.me().READ_IDLE_SECONDS,
									ServerConfig.me().WRITER_IDLE_SECONDS,
									ServerConfig.me().ALL_IDLE_SECONDS));
					ch.pipeline().addLast(new RequestDecoder());
					ch.pipeline().addLast(new ResponseEncoder());
					ch.pipeline().addLast(serviceGroup, new ServerHandler());
				}
			});
			serverBootstrap.option(ChannelOption.SO_BACKLOG, ServerConfig.me().SO_BACKLOG);

			// 绑定端口
			serverBootstrap.bind(ServerConfig.me().SERVER_PORT).sync();

			LogKit.info("服务器启动成功！" + "当前绑定端口为：" + ServerConfig.me().SERVER_PORT);
		} catch (Exception e) {
			LogKit.error("服务器启动失败！", e);
		}
	}
	
	/**
	 * @Description 关闭叮叮服务器
	 * @author fengshuonan
	 */
	public void stop(){
		bossGroup.shutdownGracefully();
		workerGroup.shutdownGracefully();
		serviceGroup.shutdownGracefully();
	}

}
